<?php
class Peer
{
    // denumiri ale campurilor folosite in tabele (se folosesc doar majuscule !)
    const USER_ID   = 'USER_ID';
    const LUNA      = 'LUNA';

    const MONTH_YEAR_DELIMITER = '-';

  /**
   * Executa o interogare si returneaza coloanele specificate
   *
   * @param Criteria $criteria
   * @param array $columns
   *
   * @return array
   */
  public static function fetchColumns($peerClass, Criteria $criteria, array $columns, $addColumns = true)
  {
    if ($addColumns)
    {
      self::addColumns($criteria, $columns);
    }

    $result = array();
    $statement = $peerClass::doSelectStmt($criteria);
    while ($row = $statement->fetch(PDO::FETCH_ASSOC))
    {
      $result[] = $row;
    }

    return $result;
  }


  /**
   * Genereaza conditiile de existenta a unei entitati la o anumita data
   *
   * @param string $date (YYYY-MM-DD)
   * @param string $peerClass
   */
  public static function getDateCriterion($date, $peerClass)
  {
    $criteria = new Criteria();
    $deletedAt  = $peerClass::DELETED_AT;
    $addedAt    = $peerClass::ADDED_AT;
    $c1 = $criteria->getNewCriterion($deletedAt, null, Criteria::ISNULL);
    $c2 = $criteria->getNewCriterion($deletedAt, $date, Criteria::GREATER_THAN);
    $c3 = $criteria->getNewCriterion($addedAt, null, Criteria::ISNULL);
    $c4 = $criteria->getNewCriterion($addedAt, $date, Criteria::LESS_EQUAL);

    $c1->addOr($c2);
    $c3->addOr($c4);
    $c1->addAnd($c3);

    return $c1;
  }

  public static function doInsert($table_name, $keys, $values)
  {
    $connection = Propel::getConnection();
    $fields = implode(',', $keys);
    $bind_values = array();
    foreach ($keys as $key)
    {
      $bind_values[] = ':'.$key;
    }
    $bind = implode(',', $bind_values);

    $sql = "INSERT INTO $table_name($fields) VALUES ($bind)";

    $statement = $connection->prepare($sql);

    foreach ($values as $row)
    {
      if (isset($row[$keys[0]]))
      {
        foreach ($keys as $key)
        {
          $statement->bindValue(':'.$key, $row[$key]);

        }
        myTools::debug($statement);
      }
      else
      {
        foreach ($keys as $index => $key)
        {
          $statement->bindValue(':'.$key, $row[$index]);
        }
      }

      $result = $statement->execute();

    }
  }

  public static function save($arguments)
  {
    $user_id = sfContext::getInstance()->getUser()->getId();

    reset($arguments);
    $col_name = key($arguments);
    $parts = explode('.', $col_name, 2);
    $peer_class = ucfirst($parts[0]).'Peer';

    $selectCriteria = new Criteria();
    $selectCriteria
      ->add($peer_class::USER_ID, $user_id)
      ->add($peer_class::ID, $arguments[$peer_class::ID]);
    unset($arguments[$peer_class::ID]);

    $updateCriteria = new Criteria();
    foreach($arguments as $key => $value)
    {
      $updateCriteria->add($key, $value);
    }

    BasePeer::doUpdate($selectCriteria, $updateCriteria, Propel::getConnection());
  }

  protected static $_filters = array('trim');
  protected static function filter(&$var, array $filters = array())
  {
    if (!$filters) $filters = self::$_filters;

    foreach ($filters as $filter)
    {
      $filter = (array)$filter;
      // append '_' to filter method because it is private
      $filter[0] = '_'.$filter[0];
      if (method_exists(__CLASS__, $filter[0]))
      {
        $filter_method = $filter[0];
        $filter[0] = &$var;
        call_user_func_array(array(__CLASS__, $filter_method), $filter);
      }
    }
  }

  private static function _trim(&$var)
  {
    $var = preg_replace('/\s+/', ' ', trim($var));
  }
  private static function _uppercase(&$var)
  {
    $var = strtoupper($var);
  }
  private static function _lowercase(&$var)
  {
    $var = strtolower($var);
  }
  private static function _ucfirst(&$var)
  {
    $var = ucfirst($var);
  }
  private static function _numeric(&$var)
  {
    if (strlen($var))
    {
      $var = floatval($var);
    }
  }

  // ---- validation ------------------------------------------------------------

  private static function rule_error($arguments, $error_param)
  {
    if (!is_null($arguments['message']))
    {
      return $arguments['message'];
    }

    if (func_num_args() >= 3)
    {
      $args = func_get_args();
      $args = array_slice($args, 2);
      $message = vsprintf(sfConfig::get('app_error_'.$error_param), $args);
    }
    else
    {
      $message = sfConfig::get('app_error_'.$error_param);
    }

    return $message;
  }

  private static function not_empty_rule(array $arguments)
  {
    if (!strlen($arguments['value']))
    {
      return self::rule_error($arguments, 'empty');
    }
  }
  private static function length_rule(array $arguments)
  {
    $length = (int)@$arguments['arguments'][0];
    if ($length > 0 && strlen($arguments['value']) > $length)
    {
      return self::rule_error($arguments, 'too_long');
    }
  }
  private static function pattern_rule(array $arguments)
  {
    $pattern = @$arguments['arguments'][0];
    if (strlen($pattern) > 2 && !preg_match($pattern, $arguments['value']))
    {
      return self::rule_error($arguments, 'not_valid');
    }
  }
  private static function integer_rule(array $arguments)
  {
    $min = @$arguments['arguments'][0];
    $max = @$arguments['arguments'][1];
    $value = $arguments['value'];
    if (isset($min) && $value < $min)
    {
      return self::rule_error($arguments, 'too_small', $min);
    }
    if (isset($max) && $value > $max)
    {
      return self::rule_error($arguments, 'too_big', $max);
    }

  }

  // the rules have priorities
  private static $rules = array('not_empty', 'length', 'pattern');

  protected static function validate($value, $rules, &$error_msg)
  {
    foreach (self::$rules as $rule)
    {
      if (isset($rules[$rule]) || in_array($rule, $rules))
      {
        $method     = $rule.'_rule';
        $arguments  = array();
        $message    = null;

        if (isset($rules[$rule]))
        {
          $params = (array)$rules[$rule];
          if (isset($params['args']))
          {
            $arguments = (array)$params['args'];
          }
          elseif (isset($params['msg']))
          {
            $message = $params['msg'];
          }
          else
          {
            $arguments = $params;
          }
        }

        $validation = call_user_func(array(__CLASS__, $method), array('value' => $value, 'arguments' => $arguments, 'message' => $message));
        if (isset($validation))
        {
          $error_msg = $validation;
          break;
        }
      }
    }

  }

  public static function executeForm($formFields, $actions)
  {
    // translate field names

    // filter


    // validate
    // save


  }


    /*************************************************/
    // added at 22-10-2011 //

    /**
     * Returneaza luna de lucru,
     * in format text <luna-an>
     * sau array[luna, an]
     *
     * @param bool $asString
     * @return string | array
     */
    public static function getWorkingMonth($asString = false)
    {
        $month = 3;
        $year = 2011;

        return $asString ?
            $month . self::MONTH_YEAR_DELIMITER . $year :
            array(
                self::LUNA  => $month,
                self::AN    => $year,
            );
    }

    /**
     * Decodifica o luna, rezultand un array[luna, an]
     *
     * @param string|array $month
     * @return array
     */
    public static function decodeMonth($month)
    {
        // ... inca nu e necesar
    }

}